package io.itit.ecp.admin.provide.action.controller.miniprogram;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import icu.mhb.mybatisplus.plugln.extend.Joins;
import io.itit.ecp.admin.common.enums.IMeterDeviceEnums;
import io.itit.ecp.admin.common.enums.MeterDeviceStaticsTypeEnums;
import io.itit.ecp.admin.provide.action.resp.DeviceResp;
import io.itit.ecp.admin.provide.action.resp.ProductTypeResp;
import io.itit.ecp.admin.provide.action.resp.largescreen.FlexibleAnalysisResp;
import io.itit.ecp.admin.provide.action.resp.largescreen.FlexibleSourceDataResp;
import io.itit.ecp.admin.provide.action.resp.largescreen.FlexibleSourceResp;
import io.itit.ecp.admin.provide.action.resp.miniprogram.ChargingStationStatisticsResp;
import io.itit.ecp.admin.provide.action.resp.miniprogram.EnergyStorageStatisticsResp;
import io.itit.ecp.admin.provide.action.resp.miniprogram.PowerGenerationStatisticsResp;
import io.itit.ecp.admin.server.entity.DeviceEntity;
import io.itit.ecp.admin.server.entity.EnergyDataEntity;
import io.itit.ecp.admin.server.entity.MeterDeviceEntity;
import io.itit.ecp.admin.server.entity.ProductTypeEntity;
import io.itit.ecp.admin.server.service.IDeviceService;
import io.itit.ecp.admin.server.service.IMeterDeviceService;
import io.itit.ecp.admin.server.service.IPhysicalModelService;
import io.itit.ecp.admin.server.service.IProductTypeService;
import io.itit.grass.common.provide.action.req.BasePageReq;
import io.itit.grass.common.provide.action.resp.ResultResp;
import io.itit.grass.common.server.entity.BaseEntity;
import io.itit.grass.common.server.utils.ConvertUtils;
import io.itit.grass.web.wall.utils.PageUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 小程序-光储直柔
 */
@Api(tags = "光储直柔")
@RestController
@RequiredArgsConstructor
@RequestMapping("/mini/flexible")
public class MiniFlexibleController {

    private final IDeviceService deviceService;

    private final IMeterDeviceService meterDeviceService;

    private final IProductTypeService productTypeService;

    private final IPhysicalModelService physicalModelService;

    /**
     * 柔性度源调度
     */
    @ApiOperation("柔性度源调度")
    @GetMapping("flexibleSource")
    public ResultResp<List<FlexibleSourceResp>> flexibleSource() {
        List<FlexibleSourceResp> list = new ArrayList<>();
        list.add(new FlexibleSourceResp().setId("1").setName("照明"));
        list.add(new FlexibleSourceResp().setId("2").setName("充电桩"));
        list.add(new FlexibleSourceResp().setId("3").setName("热储"));
        list.add(new FlexibleSourceResp().setId("4").setName("储能"));
        return ResultResp.success(list);
    }


    /**
     * 柔性度源调度情况-图表数据
     *
     * @param id id
     */
    @ApiOperation("柔性度源调度情况-图表数据")
    @GetMapping("flexibleSourceData")
    public ResultResp<List<FlexibleSourceDataResp>> flexibleSourceData(@RequestParam String id) {
        List<FlexibleSourceDataResp> list = new ArrayList<>();
        list.add(new FlexibleSourceDataResp().setName("最大可调功率").setData(Arrays.asList(
                new FlexibleSourceDataResp.DataItem().setValue(BigDecimal.ZERO).setTime("2024-06-01 10:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("23")).setTime("2024-06-01 11:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("29")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleSourceDataResp().setName("最小可调功率").setData(Arrays.asList(
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("40")).setTime("2024-06-01 10:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("50")).setTime("2024-06-01 11:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("70")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleSourceDataResp().setName("标准运行功率").setData(Arrays.asList(
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("39")).setTime("2024-06-01 10:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("60")).setTime("2024-06-01 11:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("79")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleSourceDataResp().setName("柔性调度功率").setData(Arrays.asList(
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("70")).setTime("2024-06-01 10:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("41")).setTime("2024-06-01 11:00:00"),
                new FlexibleSourceDataResp.DataItem().setValue(new BigDecimal("81")).setTime("2024-06-01 12:00:00")
        )));
        return ResultResp.success(list);
    }


    /**
     * 柔性度分析
     */
    @ApiOperation("柔性度分析")
    @GetMapping("flexibleAnalysis")
    public ResultResp<List<FlexibleAnalysisResp>> flexibleAnalysis() {
        List<FlexibleAnalysisResp> list = new ArrayList<>();
        list.add(new FlexibleAnalysisResp().setName("照明").setData(Arrays.asList(
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("52")).setTime("2024-06-01 10:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("29")).setTime("2024-06-01 11:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("66")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleAnalysisResp().setName("充电桩").setData(Arrays.asList(
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("28")).setTime("2024-06-01 10:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("51")).setTime("2024-06-01 11:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("70")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleAnalysisResp().setName("热储").setData(Arrays.asList(
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("39")).setTime("2024-06-01 10:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("43")).setTime("2024-06-01 11:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("79")).setTime("2024-06-01 12:00:00")
        )));
        list.add(new FlexibleAnalysisResp().setName("储能").setData(Arrays.asList(
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("70")).setTime("2024-06-01 10:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("20")).setTime("2024-06-01 11:00:00"),
                new FlexibleAnalysisResp.DataItem().setValue(new BigDecimal("33")).setTime("2024-06-01 12:00:00")
        )));
        return ResultResp.success(list);
    }

    @ApiOperation("查询产品类型")
    @GetMapping("productTypeList")
    public ResultResp<List<ProductTypeResp>> productTypeList() {
        List<ProductTypeEntity> list = productTypeService.lambdaQuery()
                .in(ProductTypeEntity::getProductTypeName, Arrays.asList("光伏", "储能", "充电桩"))
                .list();
        return ResultResp.success(ConvertUtils.convert(list, ProductTypeResp.class));
    }

    /**
     * 设备查询
     *
     * @param productTypeId 产品类型Id
     */
    @ApiOperation("产品类型查询设备")
    @GetMapping("deviceList")
    public ResultResp<List<DeviceResp>> deviceList(@RequestParam String productTypeId) {
        List<DeviceResp> deviceList = deviceService.lambdaQuery()
                .eq(DeviceEntity::getProductTypeId, productTypeId)
                .orderByAsc(DeviceEntity::getDeviceCode)
                .list()
                .stream()
                .map(item -> ConvertUtils.convert(item, DeviceResp.class)).collect(Collectors.toList());
        ;
        return ResultResp.success(deviceList);
    }

    /**
     * @param deviceCode 设备编码
     */
    @ApiOperation("光伏发电统计")
    @GetMapping("powergenerationstatistics")
    public ResultResp<PowerGenerationStatisticsResp> powerGenerationStatistics(@RequestParam String deviceCode,
                                                                               @RequestParam(required = false) String startTime,
                                                                               @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        DeviceEntity deviceEntity = deviceService.lambdaQuery()
                .eq(DeviceEntity::getDeviceCode, deviceCode)
                .one();
        List<MeterDeviceEntity> meterDeviceEntities = meterDeviceService.lambdaQuery()
                .eq(MeterDeviceEntity::getDeviceId, deviceEntity.getId())
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDeviceEntities.stream().map(BaseEntity::getId).collect(Collectors.toSet());
        PowerGenerationStatisticsResp resp = new PowerGenerationStatisticsResp();
        // 光伏发电量
        BigDecimal powerGeneration = meterDeviceIds.isEmpty() ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add("SUM(meter_value)", "meterValue", false))
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType11.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinGetOne(BigDecimal.class), BigDecimal.ZERO);
        // 光伏上网电量
        BigDecimal onGrid = meterDeviceIds.isEmpty() ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add("SUM(meter_value)", "meterValue", false))
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType13.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ON_GRID_ENERGY.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinGetOne(BigDecimal.class), BigDecimal.ZERO);
        // 消纳率=(光伏发电量-上网电量)/光伏发电量*100%
        resp.setConsumptionRate(powerGeneration.doubleValue() == 0.0D ? BigDecimal.ZERO : (powerGeneration.subtract(onGrid))
                .divide(powerGeneration.multiply(new BigDecimal("100")), 2, RoundingMode.HALF_DOWN));

        // 管理后台-设备列表-运行状态-装机容量（ 对应设备的装机容量）
        resp.setCurrentPower(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "装机容量", start, end));
        // 最近时间的计量值/时间（15分钟的计量值*0.25）【现在数据的颗粒度为15分钟】
        BasePageReq pageReq = new BasePageReq();
        pageReq.setPage(1);
        pageReq.setLimit(1);
        List<EnergyDataEntity> records = meterDeviceIds.isEmpty() ? Collections.emptyList() : Joins.of(EnergyDataEntity.class).select(EnergyDataEntity::getMeterValue)
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyDataEntity::getSolidifyDate)
                .joinPage(PageUtils.getPage(pageReq, EnergyDataEntity.class), EnergyDataEntity.class).getRecords();
        resp.setInstalledCapacity(CollectionUtils.isEmpty(records) ? BigDecimal.ZERO : records.get(0).getMeterValue().multiply(new BigDecimal("0.25"))
                .setScale(2, RoundingMode.HALF_DOWN));
        List<PowerGenerationStatisticsResp.StaticsInfo> staticsInfos = new ArrayList<>();

        Map<String, List<EnergyDataEntity>> solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType11.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));

        List<PowerGenerationStatisticsResp.DataItem> dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new PowerGenerationStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }
        staticsInfos.add(new PowerGenerationStatisticsResp.StaticsInfo()
                .setName("光伏发电量")
                .setDataItems(dataItems)
        );

        solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType11.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ON_GRID_ENERGY.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));

        dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new PowerGenerationStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }
        staticsInfos.add(new PowerGenerationStatisticsResp.StaticsInfo()
                .setName("上网电量")
                .setDataItems(dataItems)
        );
        resp.setStaticsInfos(staticsInfos);
        return ResultResp.success(resp);
    }

    /**
     * 储能统计
     *
     * @param deviceCode 设备编码
     */
    @ApiOperation("储能统计")
    @GetMapping("energystoragestatistics")
    public ResultResp<EnergyStorageStatisticsResp> energyStorageStatistics(@RequestParam String deviceCode,
                                                                           @RequestParam(required = false) String startTime,
                                                                           @RequestParam(required = false) String endTime) {
        LocalDateTime start = LocalDate.now().with(TemporalAdjusters.firstDayOfYear()).atTime(LocalTime.MIN);
        LocalDateTime end = LocalDate.now().with(TemporalAdjusters.lastDayOfYear()).atTime(LocalTime.MAX);
        DeviceEntity deviceEntity = deviceService.lambdaQuery()
                .eq(DeviceEntity::getDeviceCode, deviceCode)
                .one();
        List<MeterDeviceEntity> meterDeviceEntities = meterDeviceService.lambdaQuery()
                .eq(MeterDeviceEntity::getDeviceId, deviceEntity.getId())
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDeviceEntities.stream().map(BaseEntity::getId).collect(Collectors.toSet());

        // 储能设备年累计充电量
        BigDecimal yearMeterValue = meterDeviceIds.isEmpty() ? BigDecimal.ZERO : ObjectUtil.defaultIfNull(Joins.of(EnergyDataEntity.class)
                .selectAs(builder -> builder.add("SUM(meter_value)", "meterValue", false))
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType12.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_CHARGING.getValue())
                .ge(EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinGetOne(BigDecimal.class), BigDecimal.ZERO);

        start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();
        // 储能额定容量: 管理后台-设备列表-运行状态-额定容量（ 对应上方筛选设备的装机容量）
        BigDecimal ratedCapacity = physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "额定容量", start, end);


        EnergyStorageStatisticsResp resp = new EnergyStorageStatisticsResp();
        // 储能利用率=储能设备年累计充电量/（储能额定容量*365）*100%
        BigDecimal val = ratedCapacity
                .multiply(new BigDecimal("365")).multiply(new BigDecimal("100"));
        resp.setEnergyStorage(ratedCapacity.doubleValue() == 0.0D ? BigDecimal.ZERO : yearMeterValue.divide(val, 2, RoundingMode.HALF_DOWN));
        resp.setChargingCycles(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "充电次数", start, end).intValue()); // 管理后台-设备列表-运行状态-充电次数/放电次数（ 根据顶部筛选时间将之相加）
        resp.setDischargeFrequency(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "放电次数", start, end).intValue());

        resp.setCurrentPower(getEnergyStorageStatisticsCurrentPower(deviceCode, start, end));

        resp.setEnergyStorageCapacity(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "储能容量", start, end));
        resp.setChargeState(BigDecimal.ZERO);//
        resp.setHealthState(BigDecimal.ZERO);

        Map<String, List<EnergyDataEntity>> solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType12.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_CHARGING.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));
        List<EnergyStorageStatisticsResp.DataItem> dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new EnergyStorageStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }
        List<EnergyStorageStatisticsResp.StaticsInfo> staticsInfos = new ArrayList<>();
        staticsInfos.add(new EnergyStorageStatisticsResp.StaticsInfo().setName("储能充电量")
                .setDataItems(dataItems));


        solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType12.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_DISCHARGE.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));
        dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new EnergyStorageStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }
        staticsInfos.add(new EnergyStorageStatisticsResp.StaticsInfo().setName("储能放电量")
                .setDataItems(dataItems));
        resp.setStaticsInfos(staticsInfos);
        return ResultResp.success(resp);
    }

    private BigDecimal getEnergyStorageStatisticsCurrentPower(String deviceCode, LocalDateTime start, LocalDateTime end) {
        BasePageReq pageReq = new BasePageReq();
        pageReq.setPage(1);
        pageReq.setLimit(1);
        List<EnergyDataEntity> records = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getMeterValue)
                .eq(EnergyDataEntity::getDeviceCode, deviceCode)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType12.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyDataEntity::getSolidifyDate)
                .joinPage(PageUtils.getPage(pageReq, EnergyDataEntity.class), EnergyDataEntity.class).getRecords();
        // 充电计量值
        BigDecimal value = CollectionUtils.isEmpty(records) ? BigDecimal.ZERO : records.get(0).getMeterValue();
        List<EnergyDataEntity> records2 = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getMeterValue)
                .eq(EnergyDataEntity::getDeviceCode, deviceCode)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType12.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_DISCHARGE.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyDataEntity::getSolidifyDate)
                .joinPage(PageUtils.getPage(pageReq, EnergyDataEntity.class), EnergyDataEntity.class).getRecords();

        // 充电计量值
        BigDecimal value2 = CollectionUtils.isEmpty(records2) ? BigDecimal.ZERO : records2.get(0).getMeterValue();
        return (value.add(value2)).multiply(new BigDecimal("0.25")).setScale(2, RoundingMode.HALF_DOWN);
    }


    private void chargingStationCurrentPowerAndState(String deviceCode, LocalDateTime start, LocalDateTime end, ChargingStationStatisticsResp resp) {
        BasePageReq pageReq = new BasePageReq();
        pageReq.setPage(1);
        pageReq.setLimit(1);
        List<EnergyDataEntity> records = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getMeterValue)
                .eq(EnergyDataEntity::getDeviceCode, deviceCode)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType41.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.POWER_GENERATION.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyDataEntity::getSolidifyDate)
                .joinPage(PageUtils.getPage(pageReq, EnergyDataEntity.class), EnergyDataEntity.class).getRecords();
        // 充电计量值
        BigDecimal value = CollectionUtils.isEmpty(records) ? BigDecimal.ZERO : records.get(0).getMeterValue();

        List<EnergyDataEntity> records2 = Joins.of(EnergyDataEntity.class)
                .select(EnergyDataEntity::getMeterValue)
                .eq(EnergyDataEntity::getDeviceCode, deviceCode)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType41.readMeterType)
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_DISCHARGE.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyDataEntity::getSolidifyDate)
                .joinPage(PageUtils.getPage(pageReq, EnergyDataEntity.class), EnergyDataEntity.class).getRecords();

        // 放电计量值
        BigDecimal value2 = CollectionUtils.isEmpty(records2) ? BigDecimal.ZERO : records2.get(0).getMeterValue();
        BigDecimal power = (value.add(value2)).multiply(new BigDecimal("0.25"));
        resp.setCurrentPower(power.setScale(2, RoundingMode.HALF_DOWN));
        resp.setState(value.compareTo(value2) > 0 ? "放电" : "充电");
    }

    /**
     * 充电桩统计
     *
     * @param deviceCode 设备编码
     */
    @ApiOperation("充电桩统计")
    @GetMapping("chargingstationstatistics")
    public ResultResp<ChargingStationStatisticsResp> chargingStationStatistics(@RequestParam String deviceCode,
                                                                               @RequestParam(required = false) String startTime,
                                                                               @RequestParam(required = false) String endTime) {
        LocalDateTime start = StringUtils.hasLength(startTime) ? LocalDate.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MIN) : null;
        LocalDateTime end = StringUtils.hasLength(endTime) ? LocalDate.parse(endTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atTime(LocalTime.MAX) : LocalDateTime.now();

        DeviceEntity deviceEntity = deviceService.lambdaQuery()
                .eq(DeviceEntity::getDeviceCode, deviceCode)
                .one();
        List<MeterDeviceEntity> meterDeviceEntities = meterDeviceService.lambdaQuery()
                .eq(MeterDeviceEntity::getDeviceId, deviceEntity.getId())
                .eq(MeterDeviceEntity::getDelFlag, IMeterDeviceEnums.DelFlag.delFlag1.delFlag)
                .list();
        Set<String> meterDeviceIds = meterDeviceEntities.stream().map(BaseEntity::getId).collect(Collectors.toSet());

        ChargingStationStatisticsResp resp = new ChargingStationStatisticsResp();
        resp.setStorage(BigDecimal.ZERO); //TODO:  充电桩利用率数据来源：待定
        resp.setChargingCycles(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "充电次数", start, end).intValue()); // 管理后台-设备列表-运行状态-充电次数/放电次数（ 根据顶部筛选时间将之加）
        resp.setDischargeFrequency(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "放电次数", start, end).intValue());
        chargingStationCurrentPowerAndState(deviceCode, start, end, resp);
        resp.setTodayInCome(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "今日收益", LocalDate.now().atStartOfDay(), LocalDateTime.now())); // 管理后台-设备列表-运行状态-今日收益
        resp.setTotalInCome(physicalModelService.queryRunningDataValueDeviceCode(deviceCode, "今日收益", start, end)); // 管理后台-设备列表-运行状态-今日收益（ 根据顶部筛选时间将之加）


        Map<String, List<EnergyDataEntity>> solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType41.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_CHARGING.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));
        List<ChargingStationStatisticsResp.DataItem> dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new ChargingStationStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }

        List<ChargingStationStatisticsResp.StaticsInfo> staticsInfos = new ArrayList<>();
        staticsInfos.add(new ChargingStationStatisticsResp.StaticsInfo().setName("充电桩充电量")
                .setDataItems(dataItems));

        solidifyDateMap = meterDeviceIds.isEmpty() ? Collections.emptyMap() : Joins.of(EnergyDataEntity.class)
                .selectAs(builder ->
                        builder
                                .add("solidify_date", "solidify_date", false)
                                .add("meter_value", "meterValue", false)
                )
                .in(EnergyDataEntity::getMeterDeviceId, meterDeviceIds)
                .eq(EnergyDataEntity::getReadMeterType, IMeterDeviceEnums.ReadMeterType.readMeterType41.getValue())
                .eq(EnergyDataEntity::getStaticsType, MeterDeviceStaticsTypeEnums.ENERGY_STORAGE_DISCHARGE.getValue())
                .ge(Objects.nonNull(start), EnergyDataEntity::getSolidifyDate, start)
                .le(EnergyDataEntity::getSolidifyDate, end)
                .joinList(EnergyDataEntity.class)
                .stream()
                .collect(Collectors.groupingBy(item -> DateUtil.format(item.getSolidifyDate(), "yyyy-MM-dd HH:00")));
        dataItems = new ArrayList<>(solidifyDateMap.size());
        for (Map.Entry<String, List<EnergyDataEntity>> entry : solidifyDateMap.entrySet()) {
            dataItems.add(new ChargingStationStatisticsResp.DataItem().setTime(entry.getKey())
                    .setValue(entry.getValue().stream().map(EnergyDataEntity::getMeterValue).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .setScale(2, RoundingMode.HALF_DOWN)));
        }
        staticsInfos.add(new ChargingStationStatisticsResp.StaticsInfo().setName("充电桩放电量")
                .setDataItems(dataItems));
        resp.setStaticsInfos(staticsInfos);
        return ResultResp.success(resp);
    }


}
